feat(executor): introduce workflow executor#1564
Merged
Merged
Conversation
…premature deps, add smoke test - Rewrite CLAUDE.md with project overview and architecture principles, remove changelog - Remove unused dependencies (ai-proxy, sequelize, zod) per YAGNI - Add smoke test so CI passes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… document system architecture
- Lint now covers src and test directories
- Replace require() with import, use stronger assertion (toHaveLength)
- Add System Architecture section describing Front/Orchestrator/Executor/Agent
- Mark Architecture Principles as planned (not yet implemented)
- Remove redundant test/.gitkeep
- Make index.ts a valid module with export {}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…erver (#1504) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: alban bertolini <albanb@forestadmin.com>
…+ DatabaseStore) (#1506)
…xecutor factories (#1510)
…ain (#1512) Co-authored-by: alban bertolini <albanb@forestadmin.com>
- Remove McpClient.tools property, loadTools() returns local array - Rename closeConnections() → dispose() - Rename testConnections() → checkConnection() - Add McpServers type export - Rename mcpServerConfigs → toolConfigs in create-ai-provider - Update all tests accordingly Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eability Add sourceId to McpToolRef so that persisted execution data (pendingData, executionParams) tracks which MCP server provided the tool. This fixes tool lookup on re-entry (confirmation flow) when multiple servers expose tools with the same name. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… collection schema - Replace non-null assertion with explicit McpToolNotFoundError when AI selects a tool name that doesn't match any available tool - Resolve related collection name from parent schema before looking up the related schema in cache, fixing cases where relation name differs from target collection name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge main into feature branch, resolve conflicts by taking main's versions of router.ts, create-ai-provider.ts and their tests. Remove deleted mcp-config-checker.ts. Bump workflow-executor internal deps to match main. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ing provider errors [PRD-409] (#1609) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: alban bertolini <albanb@forestadmin.com>
…s (PRD-432) (#1620) The executor mints the JWT it sends to the agent from StepUser (camelCase). Ruby/Python agents splat JWT claims straight into Caller.new, which requires snake_case kwargs (first_name, last_name, rendering_id, permission_level), so the call failed with a 500 ArgumentError. The TS agent reads camelCase. There is no single canonical casing, so emit both: the Ruby Caller absorbs the extra camelCase keys via **_extra_args and the TS agent ignores the snake_case ones. fixes PRD-432 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…e [PRD-430] (#1621) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rchestrator boundaries (#1594)
…tring (PRD-437) (#1622) * fix(agent-client): serialize fields[] projection as comma-separated string (PRD-437) QuerySerializer.formatFields returned an array for the sparse fieldset projection (e.g. { 'fields[Customer]': ['first_name','last_name','email'] }). superagent serializes arrays via qs.stringify(obj, { indices: false }) as repeated keys without brackets: fields[Customer]=first_name&fields[Customer]=last_name&fields[Customer]=email Rack-based (Ruby) agents collapse duplicate scalar keys to the LAST value, so parse_projection (which does fields.split(',')) only ever saw the last field. A getData/read-record reading first_name, last_name, email returned only email (plus the primary key). The TS agent was unaffected by luck: it does fields.toString().split(','), and Array.toString() rejoins with commas. Join each projection into a single comma-separated value (JSON:API sparse fieldset standard), which both Ruby (split) and Node agents parse correctly. Also fixes the same class of issue for update-record and getRelatedData, which share this serialization. Sibling of PRD-273 #8 (filter operator casing). Update the mcp-server consumer tests that asserted the old array shape, and tighten the field assertions to token-based matching (no substring matches). fixes PRD-437 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#1623) fix(workflow-executor): drop dead-branch steps from context (PRD-433) Revising a step forks the run history: the orchestrator stamps the pivot card revised and the downstream branch cancelled, then re-appends the still-valid steps as clones carrying originalStepIndex. The executor read that history branch-blind, so re-executed steps inherited stale AI context and the record pool offered records loaded by superseded steps (e.g. revising "Load store" proposed loading from the dead branch's owner). previousSteps now mirrors the orchestrator's own live-path filter (!revised && !cancelled). resolveStepExecution then resolves a step's RunStore execution own-index-first: a step the executor ran has its entry at its own stepIndex; a revision clone ‚Äî which never ran ‚Äî falls back to originalStepIndex, where the copied step's record lives (mirroring the frontend's carry-forward, resolved on read rather than copied). The fallback is gated on a non-error outcome, so a re-executed step that produced no record (failed / skipped / handled manually) never resurfaces its superseded original's record. Records are never keyed by stepName: LinkTo loops make names non-unique on the live path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: alban bertolini <albanb@forestadmin.com>
…d route [PRD-450] (#1629) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e browser engine [PRD-449] (#1631)
…olumnType [PRD-464] (#1632)
…t [PRD-450] (#1636) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: alban bertolini <albanb@forestadmin.com>
…tep-mapper # Conflicts: # package.json # yarn.lock
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
yarn no longer nests @ForestAdmin packages under packages/*/node_modules, so the rm -rf workaround is a no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
matthv
approved these changes
Jun 9, 2026
forest-bot
added a commit
that referenced
this pull request
Jun 9, 2026
# @forestadmin/ai-proxy [1.11.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/ai-proxy@1.10.1...@forestadmin/ai-proxy@1.11.0) (2026-06-09) ### Features * **executor:** introduce workflow executor ([#1564](#1564)) ([1545069](1545069))
forest-bot
added a commit
that referenced
this pull request
Jun 9, 2026
# @forestadmin/forestadmin-client [1.40.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/forestadmin-client@1.39.9...@forestadmin/forestadmin-client@1.40.0) (2026-06-09) ### Features * **executor:** introduce workflow executor ([#1564](#1564)) ([1545069](1545069)) ### Dependencies * **@forestadmin/ai-proxy:** upgraded to 1.11.0
forest-bot
added a commit
that referenced
this pull request
Jun 9, 2026
# @forestadmin/agent-client [1.6.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.5.10...@forestadmin/agent-client@1.6.0) (2026-06-09) ### Features * **executor:** introduce workflow executor ([#1564](#1564)) ([1545069](1545069)) ### Dependencies * **@forestadmin/forestadmin-client:** upgraded to 1.40.0
forest-bot
added a commit
that referenced
this pull request
Jun 9, 2026
# @forestadmin/mcp-server [1.12.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/mcp-server@1.11.11...@forestadmin/mcp-server@1.12.0) (2026-06-09) ### Features * **executor:** introduce workflow executor ([#1564](#1564)) ([1545069](1545069)) ### Dependencies * **@forestadmin/agent-client:** upgraded to 1.6.0 * **@forestadmin/forestadmin-client:** upgraded to 1.40.0
forest-bot
added a commit
that referenced
this pull request
Jun 9, 2026
# @forestadmin/agent [1.79.0](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent@1.78.13...@forestadmin/agent@1.79.0) (2026-06-09) ### Features * **executor:** introduce workflow executor ([#1564](#1564)) ([1545069](1545069)) ### Dependencies * **@forestadmin/forestadmin-client:** upgraded to 1.40.0 * **@forestadmin/mcp-server:** upgraded to 1.12.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MAIN BRANCH TO INTRODUCE WORKFLOW EXECUTOR.
Note
Add workflow executor package with step executors, HTTP API, and CLI
@forestadmin/workflow-executorpackage that runs Forest Admin workflow steps (condition, read-record, update-record, trigger-action, load-related-record, mcp, guidance) against agent data with AI assistance.Runnerwith start/stop lifecycle, polling, in-flight run tracking, and graceful drain-on-shutdown; step execution is handled by per-type executors derived fromBaseStepExecutorwith timeout enforcement and idempotency checks.ExecutorHttpServer) with JWT auth,/health,GET /runs/:runId, andPOST /runs/:runId/triggerendpoints; the agent gains aworkflowExecutorUrloption and a proxy route (WorkflowExecutorProxyRoute) that forwards/_internal/workflow-executions/*to the executor.DatabaseStore(with Umzug migrations) or anInMemoryStore; activity log transitions are tracked and drained viaActivityLogDrainer.@forestadmin/ai-proxywithAiClient,createBaseChatModel,mcpServerIdpropagation acrossRemoteToolsubclasses, andvalidateAiConfigurations; fixesQuerySerializer.formatFieldsto emit comma-separated strings instead of arrays to prevent field loss in Rack-based agents.QuerySerializerchange alters serialized query parameter format for field projections, which may affect any consumers relying on the previous array format.Macroscope summarized 6aa8faa.